﻿

using GCCGrpc.APMServer;

using Grpc.Core;
using Grpc.Net.Client;

namespace System.APMServer.Client
{
    /// <summary>
    /// APM服务的客户端
    /// </summary>
    public class Manager
    {
        private readonly GrpcChannel _channel;
        private readonly System.Threading.Channels.Channel<(SetTraceInfoRequest, Metadata)> _requestPool = System.Threading.Channels.Channel.CreateUnbounded<(SetTraceInfoRequest, Metadata)>();
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="hostName">目标服务地址</param>
        public Manager(string hostName)
        {
            _channel = GrpcChannel.ForAddress(hostName, new GrpcChannelOptions()
            {
                HttpHandler = new SocketsHttpHandler
                {
                    EnableMultipleHttp2Connections = true,
                }
            });
            Job();
        }

        private void Job()
        {
            _ = Task.Factory.StartNew(async () =>
            {
                var reader = _requestPool.Reader;
                await foreach (var item in reader.ReadAllAsync())
                {
                    try
                    {
                        _ = await new APM.APMClient(_channel).SetTraceInfoAsync(item.Item1, item.Item2);
                    }
                    catch
                    {
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// 发送一个跟踪信息
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="sessionID">对话ID</param>
        /// <param name="resourceName">资源秒数</param>
        /// <param name="pointName">点名称</param>
        /// <param name="value">信息</param>
        /// <param name="path">路径</param>
        /// <param name="from">从哪里来</param>
        /// <param name="method">函数</param>
        /// <param name="currentEventID">当前追踪事件ID</param>
        public void SendTraceItem(string type
            , string sessionID
            , string resourceName = ""
            , string pointName = ""
            , string value = ""
            , string path = ""
            , string from = ""
            , string method = ""
            , string currentEventID = "")
        {
            var metaData = new Metadata();
            if (!string.IsNullOrEmpty(currentEventID))
            {
                metaData.Add("GCCEventID", currentEventID);
            }

            _ = _requestPool.Writer.TryWrite((new SetTraceInfoRequest()
            {
                PointName = pointName,
                ResourceName = resourceName,
                SessionID = sessionID,
                Type = type,
                Value = value,
                CreatedTime = DateTime.Now.ToUniversalTime().Ticks,
                From = from,
                Method = method,
                Path = path,
            }, metaData));
        }

        /// <summary>
        /// 根据最小ID获取对应服务器的trace信息
        /// </summary>
        /// <param name="minPID">最小ID</param>
        /// <returns></returns>
        public GetTraceInfoByTimeResponse GetTraceItems(long minTime)
        {
            var res = new APM.APMClient(_channel).GetTraceInfoByTime(new GetTraceInfoByTimeRequest()
            {
                MinTime = minTime
            });
            return res;
        }
    }
}